﻿#region License

// Droid Manager - An Android Phone Tools Suite
// Copyright (C) 2011
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#endregion

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using DroidManager.Data;
using DroidManager.Data.DeviceInfo;
using DroidManager.Data.Utils;
using DroidManager.Log;
using Managed.Adb;

namespace DroidManager.Android
{
    /// <summary>
    /// Manages Connected Android Devices
    /// </summary>
    internal class DeviceManager
    {
        /// <summary>
        /// Logger Var
        /// </summary>
        private Logger _log = Logger.Instance;

        /// <summary>
        /// Used to close adb only if started by droid manager
        /// </summary>
        private bool _adbStarted = false;

        /// <summary>
        /// Used to start and manage Adb Server
        /// </summary>
        private AndroidDebugBridge _adb;

        /// <summary>
        /// Used to communicate with adb server
        /// </summary>
        private AdbHelper _adbh;

        /// <summary>
        /// Used to store DeviceManager instance
        /// </summary>
        private static DeviceManager _instance = null;

        /// <summary>
        /// Constructor method: starts adb server
        /// </summary>
        internal DeviceManager()
        {
            _instance = this;
            StartAdb();
            AndroidDebugBridge.Initialize(true);
            _adb = AndroidDebugBridge.CreateBridge();
            _adb.Start();
            _adbh = AdbHelper.Instance;
        }

        /// <summary>
        /// Runs Adb Server
        /// </summary>
        private void StartAdb()
        {
            try
            {
                if (!Generic.IsProcessOpen("adb"))
                {
                    _adbStarted = true;
                    Process p = new Process();
                    p.StartInfo.UseShellExecute = false;
                    p.StartInfo.CreateNoWindow = true;
                    p.StartInfo.FileName = GlobalVars.AdbFilePath;
                    p.StartInfo.Arguments = "devices";
                    p.Start();
                }
            }
            catch (Exception e)
            {
                _log.Error("Error while starting adb: " + e.ToString());
                MessageBox.Show("Error while starting adb. App will now close.", "Droid Manager - Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(1);
            }
        }

        /// <summary>
        /// Stops Adb Server if started by droid manager
        /// </summary>
        internal void Stop()
        {
            if (_adbStarted)
            {
                Process p = new Process();
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.Arguments = "/C taskkill /F /IM adb.exe";
                p.Start();
            }
        }

        /// <summary>
        /// Gets device from known serial
        /// </summary>
        /// <param name="serial">Device's serial</param>
        /// <returns>Device</returns>
        internal Device GetDeviceFromSerial(string serial)
        {
            foreach (Device device in Devices)
            {
                if (device.SerialNumber.ToUpper() == serial.ToUpper())
                {
                    return device;
                }
            }
            _log.Warning(string.Format("Device with serial {0} not found.", serial.ToUpper()));
            return null;
        }

        /// <summary>
        /// Gets device from associated name
        /// </summary>
        /// <param name="name">Device's associated name</param>
        /// <returns>Device</returns>
        internal Device GetDeviceFromName(string name)
        {
            foreach (Device device in Devices)
            {
                if (device.SerialNumber.ToUpper() == name.ToUpper())
                {
                    return device;
                }
            }
            _log.Warning(string.Format("Device with name {0} not found.", name.ToUpper()));
            return null;
        }

        /// <summary>
        /// Change Device Name
        /// </summary>
        /// <param name="device">Device</param>
        /// <param name="newName">New Name</param>
        /// <returns><c>true</c> if succeded
        /// <c>false</c> if failed</returns>
        internal bool ChangeDeviceName(Device device, string newName)
        {
            try
            {
                DeviceProperties.SaveDeviceName(device, newName);
                return true;
            }
            catch (Exception e)
            {
                _log.Error(string.Format("Error while changing device ({0}) name: " + e.ToString(), device.Name));
                MessageBox.Show("Error while changing device name.", "Droid Manager - Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        #region Properties

        /// <summary>
        /// Returns Devices list
        /// </summary>
        internal List<Device> Devices
        {
            get
            {
                GC.Collect();
                List<Device> dvclist = _adbh.GetDevices(AndroidDebugBridge.SocketAddress);
                return DeviceProperties.LoadDeviceNames(dvclist);
            }
        }

        /// <summary>
        /// Returns Device Manager instance
        /// </summary>
        internal static DeviceManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new DeviceManager();
                }
                return _instance;
            }
        }

        #endregion //Properties
    }
}